#pragma once

#if defined(__GNUC__) && defined(__linux__) || defined(__CUDA_LIBDEVICE__) || defined(__CUDACC_RTC__)

#if defined(__CUDACC_RTC__)
#define __volatile__ volatile
#endif

#define __no_return__ \
    __attribute__((noreturn))

#if defined(__CUDACC__) || defined(__CUDA_ARCH__) || defined(__CUDA_LIBDEVICE__)

#define __noinline__ \
    __attribute__((noinline))
#endif

#define __align__(n) \
    __attribute__((aligned(n)))
#define __thread__ \
    __thread
#define __import__
#define __export__
#define __cdecl
#define __annotate__(a) \
    __attribute__((a))
#define __location__(a) \
    __annotate__(a)
#define CUDARTAPI
#define CUDARTAPI_CDECL

#elif defined(_MSC_VER)

#if _MSC_VER >= 1400

#define __restrict__ \
    __restrict

#else /* _MSC_VER >= 1400 */

#define __restrict__

#endif /* _MSC_VER >= 1400 */

#define __inline__ \
    __inline
#define __no_return__ \
    __declspec(noreturn)
#define __noinline__ \
    __declspec(noinline)
#define __forceinline__ \
    __forceinline
#define __align__(n) \
    __declspec(align(n))
#define __thread__ \
    __declspec(thread)
#define __import__ \
    __declspec(dllimport)
#define __export__ \
    __declspec(dllexport)
#define __annotate__(a) \
    __declspec(a)
#define __location__(a) \
    __annotate__(__##a##__)
#define CUDARTAPI \
    __stdcall
#define CUDARTAPI_CDECL \
    __cdecl

#endif

#if (defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 3 && !defined(__clang__)))) || \
    (defined(_MSC_VER) && _MSC_VER < 1900) ||                                                                \
    (!defined(__GNUC__) && !defined(_MSC_VER))

#define __specialization_static \
    static

#else

#define __specialization_static

#endif

#if !defined(__CUDACC__) && !defined(__CUDA_LIBDEVICE__)

#undef __annotate__
#define __annotate__(a)

#endif

#if defined(__CUDACC__) || defined(__CUDA_LIBDEVICE__) || \
    defined(__GNUC__) || defined(_WIN64)

#define __builtin_align__(a) \
    __align__(a)

#else

#define __builtin_align__(a)

#endif

/* TODO: Those features might be supported later. */
#define __device_builtin__
#define __device_builtin_texture_type__
#define __device_builtin_surface_type__
#define __cudart_builtin__
